﻿#region License
/* ---------------------------------------------------------------- *
 *
 * This file is part of the API Concepts Framework
 * http://apiconceptsframework.codeplex.com
 *
 * Copyright (C) 2014 eva Kühn, Thomas Scheller, Vienna University of Technology
 * http://www.complang.tuwien.ac.at/eva
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses/
 *
 * ---------------------------------------------------------------- */
#endregion

using System.Collections.Generic;
using System.Linq;
using ApiConceptsFramework.Contract;

namespace ApiConceptsFramework
{
	public static class CostCalculationExtensions
	{
		public static float CalculateSearchComplexity(this ConceptInstance c, IDE ide = IDE.VisualStudioOrSimilar)
		{
			return CalculateSearchComplexity(c, LearningEffect.Search, ide);
		}

		public static float CalculateSearchComplexity(this ConceptInstance c, LearningEffect learningEffect, IDE ide = IDE.VisualStudioOrSimilar)
		{
			var cost = c.Concept.BaseSearchComplexity + c.Concept.SearchProperties.Sum(p => p.CalculateComplexity(c.Target, ide));
			float overallCost = learningEffect.CalculateComplexityForMultipleUsages(cost, c.NumberOfUsages, c.PreviousUsages);
			overallCost += c.HcData.Sum(p => p.SearchComplexity);
			return overallCost;
		}

		public static float CalculateUsageComplexity(this ConceptInstance c, IDE ide = IDE.VisualStudioOrSimilar)
		{
			return CalculateUsageComplexity(c, LearningEffect.Usage, ide);
		}

		public static float CalculateUsageComplexity(this ConceptInstance c, LearningEffect learningEffect, IDE ide = IDE.VisualStudioOrSimilar)
		{
			var cost = c.Concept.BaseUsageComplexity + c.Concept.UsageProperties.Sum(p => p.CalculateComplexity(c.Target, ide));
			float overallCost = learningEffect.CalculateComplexityForMultipleUsages(cost, c.NumberOfUsages, c.PreviousUsages);
			overallCost += c.HcData.Sum(p => p.UsageComplexity);
			return overallCost;
		}

		public static IEnumerable<string> GetSuggestions(this ILowLevelConcept concept, MeasurableTarget target, IDE ide = IDE.VisualStudioOrSimilar)
		{
			return concept.SearchProperties.Concat(concept.UsageProperties).SelectMany(p => p.GetSuggestions(target, ide));
		}

		public static float CalculateIncrementalComplexity(this int numberOfItems, float baseComplexityPerItem, int baseComplexityStartIndex,
		                                                  float increasedComplexityValue, int increasedComplexityStartIndex)
		{
			//for caculation of complexity values that have a higher than linear increase and that are based on a certain number of items
			float complexity = 0;
			for (int i = 0; i < numberOfItems; i++)
			{
				if (i >= baseComplexityStartIndex)
					complexity += baseComplexityPerItem;
				if (i >= increasedComplexityStartIndex)
					complexity += increasedComplexityValue * (i - (increasedComplexityStartIndex - 1));
			}
			return complexity;
		}
	}
}
